<!doctype html>
<!--
@license
Copyright (c) 2017 The Polymer Project Authors. All rights reserved.
This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt
The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt
Code distributed by Google as part of the polymer project is also
subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
-->
<html>
<head>
  <meta charset="utf-8">
  <script src="../../node_modules/@webcomponents/webcomponentsjs/webcomponents-bundle.js"></script>
  <script src="wct-browser-config.js"></script>
  <script src="../../node_modules/wct-browser-legacy/browser.js"></script>
  <script type="module" src="../../polymer-legacy.js"></script>
  <style>
  .variable-override {
    border-top-width: 10px;
  }
</style>
</head>
<body>

  <simple-element></simple-element>
  <simple-element></simple-element>

  <x-scope></x-scope>

  <dom-module id="x-grand-child-scope">
    <template>
      <style>
        :host {
          display: block;
          padding: 8px;
        }

        #scope {
          border: var(--scope-var);
        }

        #child {
          border: var(--child-scope-var);
        }

        #me {
          border: var(--grand-child-scope-var);
        }

      </style>
      <div id="me">x-grand-child-scope</div>
      <div id="scope">From x-scope</div>
      <div id="child">From x-child-scope</div>
    </template>
    <script type="module">
import { Polymer } from '../../polymer-legacy.js';
Polymer({is: 'x-grand-child-scope'});
</script>
  </dom-module>

  <dom-module id="x-host-property">
    <template>
      <style>
        :host {
          display: block;
          padding: 8px;
          border: var(--scope-var);
        }

        :host(.foo) {
          border: var(--scope-var-foo);
        }
      </style>
      Host property
    </template>
    <script type="module">
import { Polymer } from '../../polymer-legacy.js';
Polymer({is: 'x-host-property'});
</script>
  </dom-module>

  <dom-module id="x-host-host-property">
    <template>
      <x-host-property id="hosted"></x-host-property>
    </template>
    <script type="module">
import { Polymer } from '../../polymer-legacy.js';
Polymer({is: 'x-host-host-property'});
</script>
  </dom-module>

  <dom-module id="x-produce-use-property">
    <template>
      <style>
        :host {
          --scope-var: 6px solid steelblue;
          --scope-var-foo: 8px solid steelblue;
        }
      </style>
      <x-host-host-property id="hosted"></x-host-host-property>
    </template>
    <script type="module">
import { Polymer } from '../../polymer-legacy.js';
Polymer({is: 'x-produce-use-property'});
</script>
  </dom-module>

  <dom-module id="x-child-scope">
    <template>
      <style>
        :host {
          display: block;
          padding: 8px;
        }

        :host > * {
          --gc4-scope: 5px solid green;
        }

        #me {
          border: var(--child-scope-var);
        }

        #gc2 {
          --grand-child-scope-var: 4px solid seagreen;
        }

        #gc4 {
          --grand-child-scope-var:
          var(--gc4-scope);
        }
      </style>
      <div id="me">x-child-scope</div>
      <x-grand-child-scope id="gc1"></x-grand-child-scope>
      <x-grand-child-scope id="gc2"></x-grand-child-scope>
      <x-grand-child-scope id="gc3"></x-grand-child-scope>
      <x-grand-child-scope id="gc4"></x-grand-child-scope>
    </template>
    <script type="module">
import { Polymer } from '../../polymer-legacy.js';
Polymer({is: 'x-child-scope'});
</script>
  </dom-module>

  <dom-module id="x-overrides">
    <template>
      <style>
        :host {
          border: 1px dashed gray;
          margin: 8px;
          padding: 8px;
          display: block;
          --grand-child-scope-var: var(--rename);
        }
      </style>
      overrides:
      <x-grand-child-scope id="gc1"></x-grand-child-scope>
    </template>
    <script type="module">
import { Polymer } from '../../polymer-legacy.js';
Polymer({is: 'x-overrides'});
</script>
  </dom-module>

  <dom-module id="x-overrides2">
    <template>
      <style>
        :host {
          border: 1px dashed gray;
          margin: 8px;
          padding: 8px;
          display: block;
        }

        :host > * {
          --grand-child-scope-var: var(--rename);
        }

      </style>
      overrides:
      <x-grand-child-scope id="gc1"></x-grand-child-scope>
    </template>
    <script type="module">
import { Polymer } from '../../polymer-legacy.js';
Polymer({is: 'x-overrides2'});
</script>
  </dom-module>

  <dom-module id="x-late">
    <template>
      <style>
        :host {
          border: var(--late);
          display: block;
        }
      </style>
      late
    </template>
    <script type="module">
import { Polymer } from '../../polymer-legacy.js';
Polymer({is: 'x-late'});
</script>
  </dom-module>

  <dom-module id="x-overrides3">
    <template>
      <style>
        :host {
          border: 1px dashed gray;
          margin: 8px;
          padding: 8px;
          display: block;
        }

        :host > * {
          --fillin: 16px;
        }
      </style>
      overrides:
      <x-late id="late"></x-late>
    </template>
    <script type="module">
import { Polymer } from '../../polymer-legacy.js';
Polymer({is: 'x-overrides3'});
</script>
  </dom-module>

  <dom-module id="x-has-def">
    <template>
      <style>
        :host {
          border: var(--border, var(--defaultBorder));
          margin: 8px;
          padding: 8px;
          display: block;
        }
      </style>
      Element with default variable.
    </template>
    <script type="module">
import { Polymer } from '../../polymer-legacy.js';
Polymer({is: 'x-has-def'});
</script>
  </dom-module>

  <dom-module id="x-has-if">
    <template>
      <style>
        .iffy {
          border: var(--scope-var);
        }
      </style>
      <template is="dom-if" if="{{gogo}}">
        <div class="iffy">iffy</div>
      </template>
    </template>
    <script type="module">
import { Polymer } from '../../polymer-legacy.js';
Polymer({
  is: 'x-has-if',
  properties: {
    gogo: {value: true}
  }
});
</script>
  </dom-module>

  <dom-module id="x-button">
    <template>
      <style>
        :host {
          display: block;
          border: var(--button-border);
        }
      </style>
      Button!
    </template>
    <script type="module">
import { Polymer } from '../../polymer-legacy.js';
Polymer({
  is: 'x-button',
  extends: 'button'
});
</script>
  </dom-module>

  <dom-module id="x-dynamic">
    <template>
      <style>
        :host {
          display: block;
          margin: 20px;
          border: var(--dynamic);
        }
      </style>
      Dynamic
    </template>
    <script type="module">
import { Polymer } from '../../polymer-legacy.js';
Polymer({
  is: 'x-dynamic'
});
</script>
  </dom-module>

  <dom-module id="x-keyframes">
    <template>
      <style>
        :host {
          display: block;
          position: relative;
          border: 10px solid blue;
          left: 0px;
          /* Prefix required by Safari <= 8 */
          -webkit-animation-duration: 0.3s;
          animation-duration: 0.3s;
          -webkit-animation-fill-mode: forwards;
          animation-fill-mode: forwards;
        }

        :host([animated]) {
          /* Prefix required by Safari <= 8 */
          -webkit-animation-name: x-keyframes-animation;
          animation-name: x-keyframes-animation;
        }

        /* Prefix required by Safari <= 8 */
        @-webkit-keyframes x-keyframes-animation {
          0% {
            left: var(--a);
          }

          100% {
            left: var(--b);
          }
        }
        @keyframes x-keyframes-animation {
          0% {
            left: var(--a);
          }

          100% {
            left: var(--b);
          }
        }
      </style>
      x-keyframes
    </template>
    <script type="module">
import { Polymer } from '../../polymer-legacy.js';
Polymer({
  is: 'x-keyframes',
  properties: {
    animated: {
      type: Boolean,
      value: false,
      reflectToAttribute: true
    }
  }
});
</script>
  </dom-module>

  <dom-module id="x-scope">
    <template>
      <style>
        :host {
          x--invalid: 15px solid gray;
          display: block;
          padding: 8px;
          --scope-var: 1px solid black;
          --fallback: 7px solid orange;
          --default1: var(--undefined, 6px solid yellow);
          --default2: var(--undefined, var(--fallback));
          --default3: var(--undefined, rgb(128, 200, 250));
          --defaultBorder: 22px solid green;
          --a: 10px;
          --b: 5px;
          --primary-color: rgb(128, 128, 128);
          --late: var(--fillin);

          --button-border: 16px solid tomato;
          --after: 17px solid brown;

          --end-term: 19px solid blue}

        :host > *{--ws-term: 18px solid orange}

        #me {
          border: var(--scope-var);
        }

        x-child-scope {
          --child-scope-var: 2px solid orange;
          --grand-child-scope-var: 3px solid steelblue;
        }

        x-child-scope.special {
          --child-scope-var: 12px solid orange;
        }

        #applyDefault1 {
          border: var(--undefined, 6px solid yellow);
        }

        #applyDefault2 {
          border: var(--undefined, var(--fallback));
        }

        #default1 {
          border: var(--default1);
        }

        #default2 {
          border: var(--default2);
        }

        #default3 {
          padding: 8px;
          background-color: var(--default3);
        }

        #defaultElement2 {
          --defaultBorder: 23px solid goldenrod;
        }

        #overrides1a, #overrides1b, #overrides2 {
          --rename: 8px solid navy;
        }

        #overrides1b, #overrides2 {
          --grand-child-scope-var: 9px solid orange;
        }

        #overridesConcrete {
          border: var(--scope-var);
          border: 4px solid steelblue;
        }

        #calc {
          border: solid red;
          border-width: calc(var(--a) + var(--b));
        }

        #shadow {
          box-shadow: 10px 10px 10px var(--primary-color);
          -webkit-box-shadow: 10px 10px 10px var(--primary-color);
        }

        x-host-property {
          border: 10px solid purple;
        }

        #invalid {
          border: var(--invalid);
        }

        #after::after {
          content: 'after';
          border: var(--after);
        }

        #wsTerm {
          border: var(--ws-term)
        }

        x-keyframes:nth-of-type(2) {
          --b: -5px;
        }

        #endTerm {border: var(--end-term)}

        #parenthesis {
          background-image: var(--foo-background-image, url(http://placehold.it/400x300));
        }

        #nestedFallback {
          border: var(--undefined, var(--undefined, 20px solid blue));
        }

        #doubleNestedFallback {
          border: var(--undefined, var(--undefined, var(--undefined, 20px solid red)));
        }

        #cornerFallback {
          background-image: var(--undefined, var(--undefined, var(--undefined, url(http://placehold.it/400x300))));
        }
      </style>
      <div id="me">x-scope</div>
      <x-keyframes id="keyframes"></x-keyframes>
      <x-keyframes id="keyframes2"></x-keyframes>
      <x-child-scope id="child"></x-child-scope>
      <x-child-scope id="child2"></x-child-scope>
      <x-overrides id="overrides1a"></x-overrides>
      <x-overrides id="overrides1b"></x-overrides>
      <x-overrides2 id="overrides2"></x-overrides2>
      <x-overrides3 id="overrides3"></x-overrides3>
      <div id="overridesConcrete">override concrete</div>
      <button id="button" is="x-button"></button>
      <div id="default1">default</div>
      <div id="default2">var default</div>
      <div id="default3">tricky property rgb(...) default</div>
      <x-has-def id="defaultElement1"></x-has-def>
      <x-has-def id="defaultElement2"></x-has-def>
      <div id="applyDefault1">default</div>
      <div id="applyDefault2">var default</div>
      <div id="calc">Calc</div>
      <div id="shadow">Shadow</div>
      <div id="invalid">invalid</div>
      <x-host-property id="hostProp"></x-host-property>
      <x-has-if id="iffy"></x-has-if>
      <div id="after"></div>
      <x-dynamic id="dynamic"></x-dynamic>
      <div id="wsTerm">new line var</div>
      <div id="endTerm">end var</div>
      <div id="parenthesis">parenthesis</div>
      <div id="nestedFallback"></div>
      <div id="doubleNestedFallback"></div>
      <div id="cornerFallback"></div>
      <div id="badFallback"></div>
    </template>
    <script type="module">
import { Polymer } from '../../polymer-legacy.js';
Polymer({
  is: 'x-scope'
});
</script>
  </dom-module>

  <dom-module id="x-inside">
    <template>
      <style>
        :host {
          display: inline-block;
          border: var(--border) solid orange;
          height: 10px;
          width: 10px;
          background-color: tomato;
        }
      </style>
    </template>
    <script type="module">
import { Polymer } from '../../polymer-legacy.js';
Polymer({
  is: 'x-inside'
});
</script>
  </dom-module>

  <dom-module id="simple-element">
    <template>
      <style>
        :host {
          display: block;
        }

        x-inside {
          color: var(--dne);
          --border: 10px;
        }
      </style>
      <x-inside id="inner"></x-inside>
    </template>
    <script type="module">
import { Polymer } from '../../polymer-legacy.js';
Polymer({
  is: 'simple-element'
});
</script>
  </dom-module>


<dom-module id="x-variable-override">
  <template>
    <style>
      :host {
        --b: 2px solid black;
        display: block;
        border: var(--b);
      }
    </style>
  </template>
  <script type="module">
import { Polymer } from '../../polymer-legacy.js';
Polymer({
  is: 'x-variable-override'
});
</script>
</dom-module>

<dom-module id="x-variable-consumer">
  <template>
    <style>
      :host(.foo) {
        border: var(--consumer);
      }
    </style>
    test
  </template>
  <script type="module">
import { Polymer } from '../../polymer-legacy.js';
Polymer({
  is: 'x-variable-consumer'
});
</script>
</dom-module>

<dom-module id="x-host-variable-consumer">
  <template>
    <style>
      :host {
        --consumer: 2px solid orange;
      }

      .foo {
        display: block;
        /* should override */
        border: 10px solid black;
      }
    </style>
    <x-variable-consumer id="consumer" class="foo"></x-variable-consumer>
  </template>
  <script type="module">
import { Polymer } from '../../polymer-legacy.js';
Polymer({
  is: 'x-host-variable-consumer'
});
</script>
</dom-module>

<dom-module id="x-var-produce-via-consume">
  <template>
    <style>
      :host {
        display: block;
        border: 10px solid orange;
        --foo: var(--bar);
      }
    </style>
        </template>
  <script type="module">
import { Polymer } from '../../polymer-legacy.js';
Polymer({
  is: 'x-var-produce-via-consume'
});
</script>
</dom-module>

<dom-module id="x-non-media-matching">
  <template>
    <style>
      @media (min-width: 100000px) {
        #inside {
          --consumer: 10px solid red;
        }
      }
    </style>
    <x-variable-consumer id="inside" class="foo"></x-variable-consumer>
  </template>
  <script type="module">
import { Polymer } from '../../polymer-legacy.js';
Polymer({
  is: 'x-non-media-matching'
});
</script>
</dom-module>

<dom-module id="x-non-media-matching-host">
  <template>
    <style>
      @media (min-width: 100000px) {
        :host {
          --border: 10px solid red;
        }
      }

      :host {
        display: block;
        border: var(--border);
      }
    </style>
  </template>
  <script type="module">
import { Polymer } from '../../polymer-legacy.js';
Polymer({
  is: 'x-non-media-matching-host'
});
</script>
</dom-module>

<dom-module id="x-update-styles">
  <template>
    <style>
      :host {
        --border: 10px solid red;
      }

      :host([active]) {
        --consumer: 6px solid orange;
      }

      :host {
        display: block;
        border: var(--border);
      }
    </style>
    <x-variable-consumer id="child" class="foo"></x-variable-consumer>
  </template>
  <script type="module">
import { Polymer } from '../../polymer-legacy.js';
Polymer({
  is: 'x-update-styles',
  properties: {
    active: {
      reflectToAttribute: true,
      observer: '_activeChanged'
    }
  },

  _activeChanged: function() {
    this.updateStyles();
  }
});
</script>
</dom-module>

<script type="module">
import { updateStyles } from '../../lib/mixins/element-mixin.js';
import { dom } from '../../lib/legacy/polymer.dom.js';
suite('scoped-styling-var', function() {

function assertComputed(element, value, pseudo, name) {
  // force a style-recalc for Safari missing updated CSS Custom Properties
  // https://bugs.webkit.org/show_bug.cgi?id=170708
  element.offsetWidth;
  name = name || 'border-top-width';
  var computed = element.getComputedStyleValue && !pseudo ?
    element.getComputedStyleValue(name) :
    getComputedStyle(element, pseudo)[name];
  assert.equal(computed, value, 'computed style incorrect');
}

function assertStylePropertyValue(element, name, includeValue) {
  var value = element.getComputedStyleValue(name);
  assert.include(value, includeValue);
}

var styled = document.querySelector('x-scope');

test('variables in @keyframes', function(done) {
  var xKeyframes = styled.$.keyframes;
  var onAnimationEnd = function() {
    assertStylePropertyValue(xKeyframes, 'left', '5px');

    xKeyframes.removeEventListener('animationend', onAnimationEnd);
    xKeyframes.removeEventListener('webkitAnimationEnd', onAnimationEnd);
    xKeyframes.animated = false;
    done();
  };

  assertStylePropertyValue(xKeyframes, '--a', '10px');
  assertStylePropertyValue(xKeyframes, '--b', '5px');

  xKeyframes.addEventListener('animationend', onAnimationEnd);
  xKeyframes.addEventListener('webkitAnimationEnd', onAnimationEnd);

  xKeyframes.animated = true;
});

test('instances of scoped @keyframes', function(done) {
  if (navigator.userAgent.match(/Safari/) && ShadyCSS.nativeCss && ShadyCSS.nativeShadow) {
    // `:nth-of-type` is broken in shadow roots on Safari 10.1
    // https://bugs.webkit.org/show_bug.cgi?id=166748
    this.skip();
  }
  var xKeyframes = styled.$.keyframes2;
  var onAnimationEnd = function() {
    assertStylePropertyValue(xKeyframes, 'left', '5px');

    xKeyframes.removeEventListener('animationend', onAnimationEnd);
    xKeyframes.removeEventListener('webkitAnimationEnd', onAnimationEnd);
    xKeyframes.animated = false;
    done();
  };

  assertStylePropertyValue(xKeyframes, '--a', '10px');
  assertStylePropertyValue(xKeyframes, '--b', '-5px');

  xKeyframes.addEventListener('animationend', onAnimationEnd);
  xKeyframes.addEventListener('webkitAnimationEnd', onAnimationEnd);

  xKeyframes.animated = true;
});

test('multiple elements in document', function() {
  var e$ = document.querySelectorAll('simple-element');
  assertComputed(e$[0].$.inner, '10px');
  assertComputed(e$[1].$.inner, '10px');
});

test('simple variables calculated correctly between scopes', function() {
   assertStylePropertyValue(styled, '--scope-var', '1px');
   //
   var child = styled.$.child;
   assertStylePropertyValue(child, '--scope-var', '1px');
   assertStylePropertyValue(child, '--child-scope-var', '2px');
   assertStylePropertyValue(child, '--grand-child-scope-var', '3px');
   //
   var gc1 = child.$.gc1;
   assertStylePropertyValue(gc1, '--scope-var', '1px');
   assertStylePropertyValue(gc1, '--child-scope-var', '2px');
   assertStylePropertyValue(gc1, '--grand-child-scope-var', '3px');
   //
   var gc2 = child.$.gc2;
   assertStylePropertyValue(gc2, '--scope-var', '1px');
   assertStylePropertyValue(gc2, '--child-scope-var', '2px');
   assertStylePropertyValue(gc2, '--grand-child-scope-var', '4px');
   //
   var gc3 = child.$.gc3;
   assertStylePropertyValue(gc3, '--scope-var', '1px');
   assertStylePropertyValue(gc3, '--child-scope-var', '2px');
   assertStylePropertyValue(gc3, '--grand-child-scope-var', '3px');

});

test('invalid variables not parsed', function() {
  if (!window.ShadyCSS || ShadyCSS.nativeCss) {
    this.skip();
  }
  assert.notOk(ShadyCSS.ScopingShim.getComputedStyleValue(styled, 'x--invalid'));
  assertComputed(styled.$.invalid, '0px');
});

test('simple variables applied correctly between scopes', function() {
   assertComputed(styled.$.me, '1px');
   assertComputed(styled.$.child.$.me, '2px');
   assertComputed(styled.$.child.$.gc1.$.me, '3px');
   assertComputed(styled.$.child.$.gc1.$.scope, '1px');
   assertComputed(styled.$.child.$.gc1.$.child, '2px');
   assertComputed(styled.$.child.$.gc2.$.me, '4px');
   assertComputed(styled.$.child.$.gc2.$.scope, '1px');
   assertComputed(styled.$.child.$.gc2.$.child, '2px');
});

test('variable can be set to another variable', function() {
  var gc4 = styled.$.child.$.gc4;
  assertStylePropertyValue(gc4, '--grand-child-scope-var', '5px');
  assertComputed(gc4.$.me, '5px');
});

test('variable default values can be assigned to other variables', function() {
  assertStylePropertyValue(styled, '--default1', '6px');
  assertStylePropertyValue(styled, '--default2', '7px');
  assertComputed(styled.$.default1, '6px');
  assertComputed(styled.$.default2, '7px');
  assertComputed(styled.$.applyDefault1, '6px');
  assertComputed(styled.$.applyDefault2, '7px');
});

test('variable literal defaults can contain one (...)', function() {
  var b = getComputedStyle(styled.$.default3).backgroundColor;
  assert.match(b, /rgb\(128/, 'literal fallback containing (...) not set');
});

test('variable values can be used with calc', function() {
  assertComputed(styled.$.calc, '15px');
});

test('variable values can be used with box-shadow', function() {
  var b = getComputedStyle(styled.$.shadow).boxShadow;
  assert.match(b, /rgb\(128/, 'box shadow not set correctly');
});

test('host properties can be overridden with outer scope styles', function() {
  assertComputed(styled.$.hostProp, '10px');
});

test('updateStyles changes property values and using style cache', function() {
  styled.$.child.classList.add('special');
  var l = document.querySelectorAll('style').length;
  styled.updateStyles();
  if (styled.shadowRoot && window.ShadyCSS && !ShadyCSS.nativeCss) {
    assert.equal(document.querySelectorAll('style').length, l+4);
  }
  assertComputed(styled.$.child.$.me, '12px');
  styled.$.child.classList.remove('special');
  styled.updateStyles();
  if (styled.shadowRoot && window.ShadyCSS && !ShadyCSS.nativeCss) {
    assert.equal(document.querySelectorAll('style').length, l);
  }
  assertComputed(styled.$.child.$.me, '2px');
});

test('Nested element uses style cache when attached and updateStyles is called', function() {
  var l = document.querySelectorAll('style').length;
  var e1 = document.createElement('x-produce-use-property');
  document.body.appendChild(e1);
  var e1t = e1.$.hosted.$.hosted;
  var e2 = document.createElement('x-produce-use-property');
  document.body.appendChild(e2);
  var e2t = e2.$.hosted.$.hosted;
  if (styled.shadowRoot && window.ShadyDOM) {
    assert.equal(document.querySelectorAll('style').length, l+1);
  }
  assertComputed(e1t, '6px');
  assertComputed(e2t, '6px');
  e1.updateStyles({'--scope-var': '8px solid purple'});
  e2.updateStyles({'--scope-var': '8px solid purple'});
  assertComputed(e1t, '8px');
  assertComputed(e2t, '8px');
  if (styled.shadowRoot && window.ShadyDOM) {
    assert.equal(document.querySelectorAll('style').length, l+1);
  }
  e1.updateStyles({'--scope-var': null});
  e2.updateStyles({'--scope-var': null});
  assertComputed(e1t, '6px');
  assertComputed(e2t, '6px');
  if (styled.shadowRoot && window.ShadyDOM) {
    assert.equal(document.querySelectorAll('style').length, l+1);
  }
});

test('updateStyles with properties argument changes styles', function() {
  styled.$.child.updateStyles({'--child-scope-var': '26px solid seagreen'});
  assertComputed(styled.$.child.$.me, '26px');
  styled.$.child.updateStyles({'--child-scope-var': null});
  assertComputed(styled.$.child.$.me, '2px');
});

test('updateStyles on when element when not attached', function() {
  var x = document.createElement('x-update-styles');
  document.body.appendChild(x);
  assertComputed(x, '10px');
  document.body.removeChild(x);
  x.updateStyles({'--border': '8px solid orange'});
  document.body.appendChild(x);
  assertComputed(x, '8px');
});

test('updateStyles called in observer when element not attached', function() {
  var x = document.createElement('x-update-styles');
  document.body.appendChild(x);
  assertComputed(x.$.child, '0px');
  x.active = true;
  assertComputed(x.$.child, '6px');
  x.active = false;
  assertComputed(x.$.child, '0px');
  document.body.removeChild(x);
  x.active = true;
  // disable element's updateStyles to show that observer for `active`'s call to updateStyles
  // functions correctly.
  x.updateStyles = function(){};
  document.body.appendChild(x);
  assertComputed(x.$.child, '6px');
});



test('styles update based on root customStyle changes', function() {
  assertComputed(styled.$.dynamic, '0px');
  updateStyles({'--dynamic': '4px solid navy'});
  assertComputed(styled.$.dynamic, '4px');
  updateStyles({'--dynamic': '6px solid gray'});
  assertComputed(styled.$.dynamic, '6px');
});

test('null customStyles unapply', function() {
  styled.$.dynamic.updateStyles({'--dynamic': '8px solid black'});
  assertComputed(styled.$.dynamic, '8px');
  styled.$.dynamic.updateStyles({'--dynamic': null});
  assertComputed(styled.$.dynamic, '6px');
  styled.$.dynamic.updateStyles({'--dynamic': '8px solid black'});
  assertComputed(styled.$.dynamic, '8px');
  styled.$.dynamic.updateStyles({'--dynamic': null});
  assertComputed(styled.$.dynamic, '6px');
});

test('style properties with dom-if', function() {
  var e = styled.$.iffy;
  var c = dom(e.root).querySelector('.iffy');
  assert.ok(c, 'dom-if did not stamp');
  assertComputed(c, '1px');
});

test('variable precedence and overrides', function() {
  // renamed property applied
  var o1a = styled.$.overrides1a;
  assertStylePropertyValue(o1a, '--rename', '8px');
  assertStylePropertyValue(o1a, '--grand-child-scope-var', '8px');
  assertComputed(o1a.$.gc1.$.me, '8px');
  // :host property overridden by outer scope
  var o1b = styled.$.overrides1b;
  assertStylePropertyValue(o1b, '--rename', '8px');
  assertStylePropertyValue(o1b, '--grand-child-scope-var', '9px');
  assertComputed(o1b.$.gc1.$.me, '9px');
  // own scope property overrides outer scope
  var o2 = styled.$.overrides2;
  assertStylePropertyValue(o2, '--rename', '8px');
  assertStylePropertyValue(o2.$.gc1, '--grand-child-scope-var', '8px');
  assertComputed(o2.$.gc1.$.me, '8px');

  // late bound property does *not* resolve using inherited value
  var o3 = styled.$.overrides3;
  if (window.ShadyCSS && !ShadyCSS.nativeCss) {
    assert.equal(ShadyCSS.ScopingShim.getComputedStyleValue(o3, '--late'), '', 'property should not be late bound');
  }
  assertStylePropertyValue(o3.$.late, '--fillin', '16px');
  assertComputed(o3.$.late, '0px');

});

test('pseudo-elements can consume custom properties', function() {
  assertComputed(styled.$.after, '17px', '::after');
});

test('elements using only variable defaults are styled properly', function() {
  assertComputed(styled.$.defaultElement1, '22px');
  assertComputed(styled.$.defaultElement2, '23px');
});

test('vars with trailing new line or } apply', function() {
  assertComputed(styled.$.wsTerm, '18px');
  assertComputed(styled.$.endTerm, '19px');
});

test('variable with parenthesis', function() {
  var url = getComputedStyle(styled.$.parenthesis).backgroundImage.replace(/['"]/g, '');
  assert.equal('url(http://placehold.it/400x300)', url);
});

test('custom style class overrides css variable', function() {
  var d = document.createElement('x-variable-override');
  d.classList.add('variable-override');
  document.body.appendChild(d);
  assertComputed(d, '10px');
});

test('class selector overrides :host(class) property on element with only dynamic styles', function() {
  var d = document.createElement('x-host-variable-consumer');
  document.body.appendChild(d);
  assertComputed(d.$.consumer, '10px');
});

test('var values can be overridden by subsequent concrete properties', function() {
  assertComputed(styled.$.overridesConcrete, '4px');
});

test('producing a var that consumes another var preserves static styling', function() {
  var d = document.createElement('x-var-produce-via-consume');
  document.body.appendChild(d);
  assertComputed(d, '10px');
});

test('producing a var that consumes results in static and not dynamic stylesheet', function() {
  if (!window.ShadyCSS || ShadyCSS.nativeCss) {
    this.skip();
  }
  var d = document.createElement('x-var-produce-via-consume');
  document.body.appendChild(d);
  var styleRoot = (!window.ShadyCSS || ShadyCSS.nativeShadow) ? d.shadowRoot : document.head;
  var staticStyle = styleRoot.querySelector('style[scope=x-var-produce-via-consume]');
  assert.ok(staticStyle);
  assert.match(staticStyle.textContent, /display/, 'static style does not contain style content');
  assert.equal(styleRoot.querySelectorAll('style[scope~=x-var-produce-via-consume]').length, 1);
});

test('Nested var fallback syntax', function() {
  assertComputed(styled.$.nestedFallback, '20px');
  assertComputed(styled.$.doubleNestedFallback, '20px');
  var url = getComputedStyle(styled.$.cornerFallback).backgroundImage.replace(/['"]/g, '');
  assert.equal('url(http://placehold.it/400x300)', url);
});

test('invalid @media rules do not match', function() {
  var e = document.createElement('x-non-media-matching');
  document.body.appendChild(e);
  assertComputed(e.$.inside, '0px');
});

test('invalid @media rules do not match :host rule', function() {
  var e = document.createElement('x-non-media-matching-host');
  document.body.appendChild(e);
  assertComputed(e, '0px');
});

});
</script>
</body>
</html>
